#!/usr/bin/perl
use strict;
use XML::Parser;
use Encode qw(from_to encode decode);
use sys;
use Digest::CRC "crc16";
use Time::HiRes qw( gettimeofday );
use Data::Dumper;
use POSIX;

die "no tid" if @ARGV < 1;
die "no database" unless -f "database.rif";

my @files = sort <renjunet_v10*.rif>;
die "no files" if 0 == scalar @files;

my @tid = @ARGV;
 
$| = 1;

my $now = time();

my $move = undef;
my $info = undef;
my %tokens;
my @hist = ();
my $last_id = "";
my $left = "";
my $right = "";

sub handle_start
{
    shift @_;
    my $token = shift @_;
    if ($token eq "move")
    {
        $move = "";
        return;
    }
    if ($token eq "info")
    {
        $info = "";
        return;
    }
    my %r = (@_);
    if (!defined $r{id})
    {
        print "ignored token $token\n";
        return;
    }

    # check for valid tournament games to add
    if ($right ne "")	# processing right file
    {
		if ($token eq "game")
		{
    		if ($r{tournament} ~~ @tid)
    		{
    			# ok
    		}
    		else
    		{
		    	$r{ignore} = 1 if !defined $tokens{$token}->{$r{id}};
    		}
		}
		elsif ($token eq "tournament")
		{
			if ($r{id} ~~ @tid)
			{
    			# ok
			}
			else
			{
		    	$r{ignore} = 1 if !defined $tokens{$token}->{$r{id}};
			}
		}
    }

    if (!defined $tokens{$token})
    {
        $tokens{$token} = {};
    }
    my $t = $tokens{$token};
    my $id = $r{id};
    $t->{$id} = \%r;
    push @hist, $token;
    $last_id = $id;
    shift @hist if @hist > 10;
}

sub enc
{
    my ($s) = (@_);
    $s =~ s/\&/&amp;/gs;
    return $s;
}

sub handle_char
{
    my ($p, $str) = @_;
    if (defined $move)
    {
#		$move .= enc($str);
		$move = "";
    }
    elsif (defined $info)
    {
    	$info .= enc($str);
    }
}

sub handle_end
{
    my $expat = shift @_;
    my $token = shift @_;
    if (defined $move)
    {
        $tokens{$hist[-1]}->{$last_id}->{move} = $move;
	    $move = undef;
    }
    if (defined $info)
    {
        $tokens{$hist[-1]}->{$last_id}->{info} = $info;
	    $info = undef;
    }
}

my $input_file = "database.rif";
$left = $input_file;
$left =~ s/\.rif$//;

print "left file: $input_file\n";

my $parser = new XML::Parser(Handlers => {Start => \&handle_start, End => \&handle_end, Char => \&handle_char});

print "parsing xml...";
$parser->parsefile($input_file, ProtocolEncoding => 'ISO-8859-1');
fix_tokens();

print "ok\n";

drop_tournaments();

$input_file = $files[-1];
$right = $input_file;
$right =~ s/\.rif$//;

print "right file: $input_file\n";

print "parsing xml...";
$parser->parsefile($input_file, ProtocolEncoding => 'ISO-8859-1');
fix_tokens();

print "ok\n";

print "dumping xml...\n";
my $f;
open $f, ">merged." . $left . "." . $right . ".rif";

my $timestamp = POSIX::strftime("%Y-%m-%d", localtime);

print $f qq(<?xml version="1.0"?>
<database version="1.0" date="$timestamp">

<!--#####################################################################################################################-->
<!-- This is an xml version of RenjuNet games database, containing following: -->
<!-- The list of countries -->
<!-- The list of cities -->
<!-- The list of months -->
<!-- The list of rules -->
<!-- The list of openings -->
<!-- The list of players -->
<!-- The list of tournaments -->
<!-- The list of games -->

<!-- The following escapes inside the texts have to be decoded into original symbols while loading/converting this file: -->
<!-- &amp; &lt; &gt; &apos; &quot; &copy; -->

<!-- COPYRIGHT INFORMATION -->
<!-- RenjuNet &copy; 2001 -->
<!-- Source: http://www.renju.net/downloads/games.php -->
<!-- E-mail: web\@renju.net -->
<!-- It is allowed to use this database for non-commercial purposes in the forms of OFFLINE databases only. -->
<!-- It is forbidden to use any contents of this database or its modifications in any website or ONLINE system. -->
<!--#####################################################################################################################-->

);

dump_section($f, "countries", "country");
dump_section($f, "cities", "city");
dump_section($f, "months", "month");
dump_section($f, "rules", "rule");
dump_section($f, "openings", "opening");
dump_section($f, "players", "player");
dump_section($f, "tournaments", "tournament");
dump_section($f, "games", "game");

sub dump_section
{
	my ($f, $sec, $key) = (@_);
	print $f "<$sec>\n";
	dump_keys($f, \%tokens, "$key");
	print $f "</$sec>\n";
	print $f "\n";
}

sub dump_keys
{
	my ($f, $tokens, $key) = (@_);
	my $r = $tokens->{$key};
	die "bad key $key" if !defined $r;
	die "empty key $key" if 0 == scalar(keys %$r);
	my @s = sort
	{
		return $a <=> $b;
	} keys %$r;
	for (@s)
	{
	    my $id = $_;
        my $h = $r->{$id};
		my $move = undef;
		my $info = undef;
		if (defined $h->{ignore} && $h->{ignore} == 1)
		{
#			print "ignored $key id=$id\n";
			next;
		}

		print $f "<$key ";
		for (sort keys %$h)
		{
			if ($_ eq "move")
			{
				$move = $h->{$_};
				next;
			}
			if ($_ eq "info")
			{
				$info = $h->{$_};
				next;
			}
			print $f $_ . qq(="$h->{$_}" );
		}
		my $autoclose = 1;
		if (defined $move || defined $info)
		{
		    $autoclose = 0;
		    print $f ">\n";
		}
		if (defined $move)
		{
			print $f "<move>$move</move>\n";
		}
		if (defined $info)
		{
			print $f "<info>$info</info>\n";
		}
		if ($autoclose)
		{
			print $f "/>\n";
		}
		else
		{
			print $f "</$key>\n";
		}
	}
}

sub drop_tournaments()
{
    for (@tid)
    {
        my $tid = $_;
        my $r = $tokens{game};
        for (keys %$r)
        {
            if ($r->{$_}->{tournament} == $tid)
            {
                print "deleting game $_\n";
                delete $r->{$_};
            }
        }
        if (exists($tokens{tournament}->{$tid}))
        {
            print "deleting tournament $tid\n";
            delete $tokens{tournament}->{$tid}->{id};
        }
    }
}

print $f "\n</database>\n";
close $f;

sub fix_tokens()
{
    open F, "duplicate_players.txt" or return;
    my $str = join("", <F>);
    close F;
    my @a = split/\n/, $str;
    my %dupes;
    for (@a)
    {
        my @b = split/\s+/, $_;
        $dupes{$b[1]} = $b[0];
    }
    
    my $g = $tokens{game};
    for (keys %$g)
    {
        my $gid = $_;
        my $b = $g->{$gid}->{black};
        my $w = $g->{$gid}->{white};
        if (defined $dupes{$b})
        {
            $g->{$gid}->{black} = $dupes{$b};
        }
        if (defined $dupes{$w})
        {
            $g->{$gid}->{white} = $dupes{$w};
        }
    }
}
